/**
 * @author salim & sidyous
 */

import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;

public class Server extends UnicastRemoteObject implements Server_itf {

	/*
	 * Attributes
	 */

	// Core
	private HashMap<String, Integer> namingServer;
	private Vector<ServerObject> serverObjectCollection;
	private AtomicInteger nextFreePosition;

	// Serialization
	private static final long serialVersionUID = 1L;
	
	/*
	 * Methods
	 */

	public Server() throws RemoteException
	{
		super();
		if (Debug.is_on) System.out.println("Server : Server");
		namingServer = new HashMap<String, Integer>();
		serverObjectCollection = new Vector<ServerObject>();
		nextFreePosition = new AtomicInteger(0);
	}

	@Override
	public int create(Object obj) throws RemoteException
	{
		if (Debug.is_on) System.out.println("Server : create");
		int id = nextFreePosition.getAndIncrement();
		serverObjectCollection.add(id, new ServerObject(obj, id));
		return id;
	}

	/**
	 * @return the id of the ServerObject. If (id == -1), it means that the object
	 *         targeted by this name doesn't exist
	 */
	@Override
	public int lookup(String name) throws RemoteException
	{
		if (Debug.is_on) System.out.println("Server : lookup " + name);
		if (namingServer.containsKey(name))	return namingServer.get(name); else return -1;
	}
	
	/**
	 * @return the Object whose with id "id"
	 */
	@Override
	public Object get(int id) throws RemoteException
	{
		if (Debug.is_on) System.out.println("Server : get " + id);
		return serverObjectCollection.get(id).obj;
	}

	@Override
	public void register(String name, int id) throws RemoteException
	{
		if (Debug.is_on) System.out.println("Server : register " + name + " " + id);
		// XXX : danger if id is not allocated yet, or if it is even registred
		namingServer.put(name, id);
	}

	@Override
	public Object lock_read(int id, Client_itf client) throws RemoteException
	{
		if (Debug.is_on) System.out.println("Server : lock_read " + id);
		return serverObjectCollection.get(id).lock_read(client);
	}

	@Override
	public Object lock_write(int id, Client_itf client) throws RemoteException
	{
		if (Debug.is_on) System.out.println("Server : lock_write " + id);
		return serverObjectCollection.get(id).lock_write(client);
	}

	public static void main(String[] args)
	{
		int port = 8081;
		String URL;
		String serverName = "remoteServer";
		try
		{
			// Creation of the rmiregistry
			Registry registry = LocateRegistry.createRegistry(port);
			// Creation of the object Server
			Server server = new Server();
			// Calculation of the URL
			URL = "//" + InetAddress.getLocalHost().getHostName() + ":" + port
					+ "/" + serverName;
			// Deployment of the server
			Naming.bind(URL, server);
			System.out.println("Server deployed under: " + URL);
		}
		catch (Exception exc)
		{
			exc.printStackTrace();
		}
	}
}
